#pragma once

#include "export.h"
#include "vec.h"
#include "quat.h"
#include "gizmos.h"
#include <string>
#include <vector>
#include <osg/node>
#include <osg/MatrixTransform>
#include <osgManipulator/Selection>

//----------------------------------------------------------------------
class DENG_EXPORT Node
//----------------------------------------------------------------------
{
public:
           Node(void);
           Node(Node* parent);
  virtual ~Node(void);

  void     Show(bool show); // not affecting the chidren
  bool     IsShown() {return _shown;};

  virtual bool     Load(std::string filename);

  virtual void  SetParent( Node *n );
  virtual Node* GetParent() {return _parent;};
  virtual int   GetNumberOfChildren() {return _children.size();};
  virtual Node* GetChild(int i)  {if(i>=GetNumberOfChildren()) return 0; else return _children[i];};
  virtual bool  AddChild(Node *n);
  virtual bool  RemoveChild(Node *n);

  virtual void     SetPosition( float x, float y, float z ) {SetPosition(Vec(x,y,z));};
  virtual void     SetPosition( Vec p );
  virtual Vec      GetPosition() { return _transform->getMatrix().getTrans(); };
  virtual void     SetRotation( Quat r );
  virtual void     SetRotation( double a, double x, double y, double z) {SetRotation(Quat(a,x,y,z));};
  virtual Quat     GetRotation() { return _transform->getMatrix().getRotate(); };
  virtual void     SetScale( Vec s ); 
  virtual void     SetScale( float x, float y, float z ) {SetScale(Vec(x,y,z));};
  virtual Vec      GetScale() { return _transform->getMatrix().getScale(); };

  virtual void     Move(Vec p);
  virtual void     Move( float x, float y, float z ) {Move(Vec(x,y,z));};
  virtual void     Rotate(Quat q);
  virtual void     Rotate( double a, double x, double y, double z) {Rotate(Quat(a,x,y,z));};
  virtual void     RotateX(float a);
  virtual void     RotateY(float a);
  virtual void     RotateZ(float a);
  virtual void     Scale(Vec s);
  virtual void     Scale( float x, float y, float z ) {Scale(Vec(x,y,z));};
  virtual void     Scale(float s);

  virtual void     SetOpacity( double opacity );
  virtual double   GetOpacity() { return _opacity;};

  virtual void ShowTool(int tool);
  virtual std::string Repr();
  virtual std::string Name();

#ifndef SWIG
  osg::Node* Get() { return _group.get(); };
#endif

protected:
  void   AddChild2(Node *n);
  //void   DoTransform();
  void   Decompose();
  void   Ricompose();

  Node* _parent;
  bool  _shown;

  osg::ref_ptr<osg::Group>                _group;
  osg::ref_ptr<osgManipulator::Selection> _transform;
  osg::ref_ptr<osg::Node>                 _node;
  osg::ref_ptr<osgManipulator::Dragger>   _dragger;

  std::vector<Node*> _children;

  // decomposed Matrix
  osg::Vec3d  _trans,_scale;
  osg::Quat   _rot,_scale_org;

  int _id;
  std::string _filename;
  double _opacity;
};




